package org.example.exam.service.impl;

import io.minio.*;
import io.minio.errors.*;
import org.example.exam.properties.MinIOProperties;
import org.example.exam.service.FileUploadService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.UUID;

/**
 * projectName: com.atguigu.exam.service.impl
 *
 * @author: 赵伟风
 * description:
 */
@Service
@Slf4j
public class FileUploadServiceImpl implements FileUploadService {

    @Autowired
    private MinioClient minioClient;
    @Autowired
    private MinIOProperties minIOProperties;

    @Override
    public String uploadFile(String folder, MultipartFile file) throws ServerException, InsufficientDataException, ErrorResponseException, IOException, NoSuchAlgorithmException, InvalidKeyException, InvalidResponseException, XmlParserException, InternalException {
        // 1、连接minio的客户端
        // 2、判断桶是否存在
        boolean exists = minioClient.bucketExists(
                BucketExistsArgs.builder()
                        .bucket(minIOProperties.getBucketName())
                        .build()
        );
        // 3、不存在创建桶，并且设置访问权限
        if (!exists) {
            // 权限
            String config = """
            {
            "Statement" : [ {
                "Action" : "s3:GetObject",
                "Effect" : "Allow",
                "Principal" : "*",
                "Resource" : "arn:aws:s3:::%s/*"
            } ],
            "Version" : "2012-10-17"
            }""".formatted(minIOProperties.getBucketName());


            // 创建桶
            minioClient.makeBucket(
                    MakeBucketArgs.builder()
                            .bucket(minIOProperties.getBucketName())
                            .build()
            );
            // 设置桶的权限
            minioClient.setBucketPolicy(
                    SetBucketPolicyArgs.builder()
                            .bucket(minIOProperties.getBucketName()) // 指定给哪个桶设置权限
                            .config(config) // 设置桶的权限
                            .build()
            );
        }
        // 4、上传文件
        // 获取UUID随机名称
        UUID uuid = UUID.randomUUID();
        // 获取文件的原始名称
        String originalFilename = file.getOriginalFilename();
        // 获取文件的后缀名
        String suffix = originalFilename.substring(originalFilename.lastIndexOf("."));
        // 拼接新的文件名
        String filename = uuid + suffix;
//        // 避免文件被覆盖
//        String newFileName = LocalDateTime.now().
//                format(DateTimeFormatter.ofPattern("yyyy-MM-dd-HH-mm-ss"))
//                + filename;

        // 希望在minio的服务器中，创建一个文件夹，在存储对象
        // 为了防止文件夹中的文件名重复，将每天上传的文件再一次进行分类
        String folderAndFileName = folder+ "/"
                + LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd")) +
                "/" + filename;

        minioClient.putObject(
                PutObjectArgs.builder()
                        .bucket(minIOProperties.getBucketName()) // 指定上传到哪一个桶里面
                        // 指定文件的类型
                        .contentType(file.getContentType())
                        .object(folderAndFileName)
                        // 传入文件的输入流的数据
                        // 参数1：上传文件的输入流
                        // 参数2：上传文件的字节大小
                        // 参数3：是否切割文件，转换多线程上传 -1表示只能切割 minio自己管理
                        .stream(file.getInputStream(), file.getSize(), -1)
                        .build()
        );


        // 5、拼接回显地址
        String url = minIOProperties.getEndpoint() + "/" + minIOProperties.getBucketName() + "/" + folderAndFileName;
        log.info("上传文件成功！回显地址为：{}",url);
        return url;
    }
}
